package com.dudetest.data.objectify;

import java.util.logging.Logger;

import com.dudetest.data.DAOVersion;
import com.dudetest.dude.Dude;
import com.dudetest.dude.DudeA;
import com.dudetest.dude.DudeAB;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.ObjectifyOpts;
import com.googlecode.objectify.ObjectifyService;

public abstract class DAOBase {
	protected static final Logger log = Logger.getLogger(DAOBase.class.getName());

	public Dude getOrCreateDude(long id, int n){
		if(id%2 == 0){
			log.info("get or create DudeA with id = "+id+". N = "+n);
			return this.getOrCreateDudeA(id);
		} else{
			log.info("get or create DudeAB with id = "+id+". N = "+n);
			return this.getOrCreateDudeAB(id);
		}
	}
	
	public abstract Dude getOrCreateDudeA(long id);
	public abstract Dude getOrCreateDudeAB(long id);
	
	public abstract DudeA getDudeA(long id);
	public abstract DudeAB getDudeAB(long id);

	@SuppressWarnings("unchecked")
	public Dude getDudeFromReference(String reference){
		return ofy().find( (Key<? extends Dude>)fact().stringToKey((reference)));
	}

	public abstract DAOVersion getVersion();

	public boolean hasGlobalCache() {
		return this.opts.getGlobalCache();
	}
	
	/*##############################
	 * Code copied from DAOBase.java
	 * @see <a href="http://code.google.com/p/objectify-appengine/source/browse/trunk/src/com/googlecode/objectify/util/DAOBase.java">DAOBase</a>
	 * @author Jeff Schnitzer
	 *##############################/

	/** Need to create the lazy Objectify object */
	protected ObjectifyOpts opts;

	/** A single objectify interface, lazily created */
	protected Objectify lazyOfy;

	/** Creates a DAO without a transaction */
	public DAOBase(){
		this.opts = new ObjectifyOpts();
	}

	/**
	 * Creates a DAO possibly with a transaction.
	 */
	public DAOBase(boolean transactional){
		this.opts = new ObjectifyOpts().setBeginTransaction(transactional);
	}

	/**
	 * Creates a DAO with a certain set of options
	 */
	public DAOBase(ObjectifyOpts opts){
		this.opts = opts;
	}

	/**
	 * Easy access to the factory object.  This is convenient shorthand for
	 * {@code ObjectifyService.factory()}.
	 */
	public ObjectifyFactory fact(){
		return ObjectifyService.factory();
	}

	/**
	 * Easy access to the objectify object (which is lazily created).
	 */
	public Objectify ofy() {
		if (this.lazyOfy == null){
			this.lazyOfy = fact().begin(this.opts);
		}
		return this.lazyOfy;
	}
}
